Skip to content

Conversation

@AlePouroullis
Copy link
Contributor

@AlePouroullis AlePouroullis commented May 7, 2025

Superseded by PR 69
p_sync/base is the auto-generated SDK with my latest backend changes from here. Did this to make the PR focused on the custom code changes.

  • Create sync client with support for pulling files from the remote humanloop to local workspace). Includes filters for environment and path (where path can specify specific file or directory)
  • Create CLI with pull command. Uses the click library
  • Overload .call() and .log() functions to use serialized contents of .prompt/.agent local files when use_local_files is set to true when initializing the humanloop client.
  • Address edge cases like specifying path + environment or path + version_id. I employ the principle of "explicit is better than implicit", i.e. raise error if user initializes the client with use_local_files=True and tries to reference path + remote-specific information (version_id/environment).
  • Cache files in memory after loading from disk using LRU cache
  • Integration tests for sync client, call and log overloading, CLI

How to Use Locally

Prerequisites

Run this backend branch locally

Set up the SDK

Clone this branch
git clone --branch p_sync/pull git@github.com:humanloop/humanloop-python.git

Install dependencies
poetry install

Activate the venv
poetry shell

Test the CLI

In the same directory as this cloned SDK
humanloop pull --base-url http://localhost:80/v5

In another project:

  1. poetry init Use default configuration
  2. In pyproject.toml modify python version constraints to >=3.9,<4
  3. Add the SDK as a dependency.
    3a. Get the absolute path to the local SDK using pwd
    3b. In your playground project run poetry add --editable <path to SDK>
  4. Then install peer dependencies poetry install
  5. From the virtual environment (poetry shell) you can test the CLI humanloop pull --base-url http://localhost:80/v5

Note that you can remove --base-url entirely as the relevant backend changes are live in prod.

@AlePouroullis AlePouroullis changed the base branch from master to p_sync/base May 7, 2025 17:29
@AlePouroullis AlePouroullis changed the title P sync/pull Create Sync Client, implement pull operation, CLI, and overloads for log + call May 7, 2025
@AlePouroullis AlePouroullis changed the title Create Sync Client, implement pull operation, CLI, and overloads for log + call p_sync Milestone 1: Create Sync Client, implement pull operation, CLI, and overloads for log + call May 7, 2025
line-length = 120

[tool.poetry.scripts]
humanloop = "humanloop.cli.__main__:cli"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

integration test: use subprocess to check if cli works

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check if exit code 0 when calling cli command; maybe check for exit code 1 when api key not provided

\b
This command will:
1. Fetch prompt and agent files from your Humanloop workspace
Copy link

@andreibratu andreibratu May 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
1. Fetch prompt and agent files from your Humanloop workspace
1. Fetch serializable files from your Humanloop workspace.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've decided against this as I don't think users will understand what 'serializable' means.

successful_files = sync_client.pull(path, environment)

# Get metadata about the operation
metadata = sync_client.metadata.get_last_operation()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

follow-up with a loom

for file in metadata['successful_files']:
click.echo(click.style(f" ✓ {file}", fg=SUCCESS_COLOR))
else:
files_to_display = metadata['successful_files'][:MAX_FILES_TO_DISPLAY]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if len(failed_failes) > 0, cancel the operation, inform user via message in terminal, exit 1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem I'm seeing with this is it would make things quite complex to support transactions, i.e. allow rollbacks if one file fails.

@olehvell-h
Copy link
Contributor

humanloop.core.api_error.ApiError: status_code: 401, body: {'detail': 'Could not validate credentials.'}

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/oleh/humanloop/playground/test-sdk/letscallhllocally.py", line 9, in <module>
    xx = humanloop.prompts.call(path="/Oleh's space/Customer Support bot.prompt")
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/oleh/humanloop/test-sync-sdk/humanloop-python/src/humanloop/overload.py", line 204, in call_wrapper
    return _overload_call(self, sync_client, use_local_files, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/oleh/humanloop/test-sync-sdk/humanloop-python/src/humanloop/overload.py", line 175, in _overload_call
    raise HumanloopRuntimeError from e
humanloop.error.HumanloopRuntimeError

I think there is an error that we don't handle properly. Would expect to see "humanloop.core.api_error.ApiError: status_code: 401, body: {'detail': 'Could not validate credentials.'}" as first line, not

....
  File "/Users/oleh/humanloop/test-sync-sdk/humanloop-python/src/humanloop/overload.py", line 204, in call_wrapper
    return _overload_call(self, sync_client, use_local_files, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/oleh/humanloop/test-sync-sdk/humanloop-python/src/humanloop/overload.py", line 175, in _overload_call
    raise HumanloopRuntimeError from e
humanloop.error.HumanloopRuntimeError

@olehvell-h
Copy link
Contributor

image

I made a typo and new file was created on HL. Curious whether it makes sense to have strict mode, where creating new files (or even versions) is not allowed if use_local_files=True . Don't want to expand scope, just sharing my observations

version = "0.8.36"
description = ""
version = "0.8.39"
description = "Humanloop Python SDK"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have you changes this? this is auto-generated by fen

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file's autogenerated by fern? Oops, thought we'd be able to modify project metadata.

@@ -0,0 +1,2 @@
[pytest]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: i have updated humanloop-docs with the pytest-xdist dependency; we'll regenerate the sdk and rebase this PR on top of it before merging

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks 🙏

@AlePouroullis AlePouroullis changed the base branch from p_sync/base to master May 13, 2025 17:14
@AlePouroullis AlePouroullis deleted the p_sync/pull branch May 16, 2025 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants